// app/controller/user.js
const BaseController = require('../core/base_controller');
const {Jieba} = require('@node-rs/jieba');
const {dict} = require('@node-rs/jieba/dict.js');
const {levenshteinSimilarity} = require('../utils/helper');

// 常见的银行相关关键词
const keywords = [ '银行', '信用合作', '支行', '分行', '营业部', '储蓄所', '办事处', '营业室', '分理处', '股份', '有限公司', '责任公司','市','区','县','镇'];

// 常见银行简称映射表
const bankAbbreviations = {
  '农行': '农业银行',
  '建行': '建设银行',
  '工行': '工商银行',
  '邮储': '邮政储蓄银行',
  '邮政银行': '邮政储蓄银行',
  '交行': '交通银行',
  '中行': '中国银行',
  '招行': '招商银行',
  '浙商': '浙江商业银行'
};

class BankController extends BaseController {
  async get() {
    // 构建参数
    const params = [];
    const paramNames = [ 'kw_1', 'kw_2', 'kw_3', 'kw_4' ];
    // throw new Error("参数错误");
    
    paramNames.forEach(paramName => {
      const value = this.getParam(paramName);
      if (value !== null) {
        params.push(value);
      }
    });

    if(params.length === 0) {
      this.fail('请输入查询参数');
      return;
    }

    // 第一步,精确查找：判断是否只传一个参数
    if (params.length === 1) {
      let result = await this.ctx.service.bank.findOne(params[0]);
      if (result.length === 1) {
        //计算返回结果相似度
        result = this.calcSimilarity(result, params[0])
        this.success({ rows: result, splitStr: []});
        return;
      } else {
        // 先替换简称
        let processedStr = params[0];
        for (const [abbr, fullName] of Object.entries(bankAbbreviations)) {
          processedStr = processedStr.replace(new RegExp(abbr, 'g'), fullName);
        }
        // 1、对传入的参数进行字符串智能切分后进行模糊匹配
        let splitParams = this.smartSplit(processedStr);

        let result = await this.ctx.service.bank.find(splitParams);
        if (result.length > 20) {
          this.fail('查询数据量过大，请调整查询条件');
          return;
        }
        // 2、如果查询结果等于0，进行结巴分词后二次模糊匹配
        if(result.length === 0) {
          splitParams = this.jiebaSplit(processedStr);

          // console.log(splitParams);
          result = await this.ctx.service.bank.find(splitParams);
          if (result.length > 20) {
            this.fail('查询数据量过大，请调整查询条件');
            return;
          }
        }
        //计算返回结果相似度
        result = this.calcSimilarity(result, processedStr)
        
        this.success({ rows: result , splitStr: splitParams});
      }
    } else {
      let result = await this.ctx.service.bank.find(params);
      if (result.length > 20) {
        this.fail('查询数据量过大，请调整查询条件');
        return;
      }
      //计算返回结果相似度
      result = this.calcSimilarity(result, params.join(''))

      this.success({ rows: result });
    }
  }

  // 关键词智能切分字符串方法
  smartSplit(str) {
    // 处理边界情况
    if (!str || typeof str !== 'string') {
      return [];
    }

    // 构建正则表达式，按长度降序排列关键词以确保长匹配优先
    const escapedKeywords = keywords.map(keyword => keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
    const regexPattern = `(${escapedKeywords.join('|')})`;
    const regex = new RegExp(regexPattern, 'g');
    
    const result = [];
    let lastIndex = 0;
    let match;
    
    // 使用正则表达式查找所有匹配项
    while ((match = regex.exec(str)) !== null) {
      // 添加匹配项之前的文本（如果存在且长度大于1）
      if (match.index > lastIndex) {
        const prefix = str.substring(lastIndex, match.index);
        result.push(prefix);
      }
      
      // 添加匹配到的关键词
      // result.push(match[0]);
      lastIndex = match.index + match[0].length;
    }
    
    // 添加末尾剩余的文本（如果存在且长度大于1）
    if (lastIndex < str.length) {
      const suffix = str.substring(lastIndex);
      result.push(suffix);
    }
    
    return result
  }

  // 使用jieba分词
  jiebaSplit(str) {
    const jieba = Jieba.withDict(dict);
    const cutStr = jieba.cut(str); 

    const result = []
    //去掉部分无效的关键词
    for (let i = 0; i < cutStr.length; i++) {
      if(!keywords.includes(cutStr[i])) {
        result.push(cutStr[i]);
      }
    }
    return result;
  }

  //计算返回结果相似度
  calcSimilarity(arr, keyword) {
    if(arr.length == 0 || keyword == '') return [];

    let MaxVal = 0;
    for (let index = 0; index < arr.length; index++) {
      const element = arr[index];
      const similarity = Math.round(levenshteinSimilarity(element.bname, keyword) * 100);
      arr[index] = {
        ...element,
        similarity
      }
      if (similarity > MaxVal) {
        MaxVal = similarity;
      }
    }

    //获取基准值
    const threshold = Math.floor((100 - MaxVal)/10) * 10 * 0.9;

    //每项元素加上基准值
    arr.forEach(element => {
      element.similarity += threshold;
    });
    // 排序
    arr.sort((a, b) => b.similarity - a.similarity);
    return arr;
  }
}

module.exports = BankController;
